﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using DoeObjects;
using DoeLibsMVC.Security;

namespace DoeLibsMVC.Controllers.api
{
    public class ReservationController : BaseApiController
    {
        /// <summary>
        /// returns all reservations for the user
        /// </summary>
        /// <returns></returns>
        [BasicAuthorize]
        public HttpResponseMessage Get()
        {
            return Request.CreateResponse<IEnumerable<Reservation>>(HttpStatusCode.OK, Reservation.getReservationsByUser(User.UserId));
        }


        /// <summary>
        /// returns the reservation for the title if the user has a available reservation.
        /// </summary>
        /// <param name="titleId"></param>
        /// <param name="availableReservation">this parameter is only a flag for this method</param>
        /// <returns></returns>
        [BasicAuthorize]
        public HttpResponseMessage Get(int titleId, string availableReservation)
        {
            List<Reservation> reservations = Reservation.getReservationsByUser(User.UserId).Where(r => r.Title.TitleId == titleId && r.LoanRecalled && r.AvailableDate != DateTime.MinValue).ToList();
            if (reservations.Count > 0)
            {
                return Request.CreateResponse<Reservation>(HttpStatusCode.OK, reservations[0]);
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
        }

        /// <summary>
        /// makes a reservation
        /// </summary>
        /// <param name="titleId"></param>
        /// <returns></returns>
        [BasicAuthorize]
        public HttpResponseMessage Post(int titleId)
        {
            Title title = Title.getById(titleId);

            if (title != null)
            {
                if (DoeObjects.Loan.getActiveLoansFromUser(User.UserId).Where(l => l.Loanable.Title.TitleId == titleId).ToList().Count > 0)
                {
                    //user has currently borrowed this title
                    return Request.CreateErrorResponse(HttpStatusCode.Forbidden, "The user has currently borrowed a loanable of this title");
                }
                else
                {
                    if (Reservation.createReservation(titleId, User.UserId))
                    {
                        return Request.CreateResponse(HttpStatusCode.Created);
                    }
                    else
                    {
                        return Request.CreateResponse(HttpStatusCode.BadRequest);
                    }
                }
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
        }

        /// <summary>
        /// returns information for the given reservation
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [BasicAuthorize]
        public HttpResponseMessage Get(int id)
        {
            Reservation res = Reservation.getById(id);

            if (res != null)
            {
                if (res.User.UserId == User.UserId)
                {
                    return Request.CreateResponse<Reservation>(HttpStatusCode.OK, res);
                }
                else
                {
                    return Request.CreateResponse(HttpStatusCode.Forbidden);
                }
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
        }

        /// <summary>
        /// Deletes a reservation
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [BasicAuthorize]
        public HttpResponseMessage Delete(int id)
        {
            Reservation res = Reservation.getById(id);

            if (res != null)
            {
                if (res.User.UserId == User.UserId)
                {
                    if (Reservation.delete(id))
                    {
                        if (res.LoanRecalled)
                        {
                            //loan was recalled --> update next reservation

                            Reservation nextReservationInQueue = Reservation.getNext(res.Title.TitleId, false);

                            if (nextReservationInQueue != null)
                            {
                                nextReservationInQueue.LoanRecalled = true;
                                nextReservationInQueue.AvailableDate = DateTime.Now;

                                if (nextReservationInQueue.save())
                                {
                                    Notification not = new Notification();
                                    not.Type = NotificationType.TITLE_RESERVATION;
                                    not.SendDate = DateTime.Now;
                                    not.Recipient = nextReservationInQueue.User;
                                    not.Message = string.Format("You reserved {}. A loanable is now available for you. Please pick it up until {}", nextReservationInQueue.Title.BookTitle, nextReservationInQueue.AvailableDate.AddDays(7).ToShortDateString());
                                    not.save();
                                }
                            }
                        }

                        return Request.CreateResponse(HttpStatusCode.OK);
                    }
                    else
                    {
                        return Request.CreateResponse(HttpStatusCode.InternalServerError);
                    }
                }
                else
                {
                    return Request.CreateResponse(HttpStatusCode.Forbidden);
                }
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
        }
    }
}
